Now
that you have the basic building blocks of designing the look of an
application, let’s talk about creating the feel of an application.
Applications should feel alive to the user. Often this is accomplished
with subtle feedback to the user including changing the look of the UI
in reaction to the user or using techniques like haptic (e.g.
vibration) feedback. This feedback is important to help the user know
they are doing something. A common example of this is the veritable
button object. In a typical desktop operating system, when you move
your mouse over a button, it changes its look to indicate you’re over
the button. When you press it, it changes the look to give you the
impression that the button is actually pressed (like a real-world
button). This feedback ensures that the user can feel confident that
pressing the button is doing what they expect. You can see the lack of
this feedback on some websites and it simply confuses users (and often
they don’t know what is missing). This is where Transformations and
Animations can help you polish your user interface design.
Tranformations
Let’s start with
transformations. The idea of a transformation is to simply change the
way that an element is drawn on the screen. Let’s take a simple
rectangle:
<Grid>
<Rectangle Width="100"
Height="100"
Fill="Red" />
</Grid>
As you would expect,
this rectangle will simply be drawn as a simple square. But if add a
transform (by assigning it to the Rectangle’s RenderTransform property):
<Grid>
<Rectangle Width="100"
Height="100"
Fill="Red">
<Rectangle.RenderTransform>
<RotateTransform Angle="30" />
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
By using a RotateTransform, the object can stay a Rectangle but when drawn the transformation is applied (as seen in Figure 1).
Using a transformation on a
single element rarely is the right thing to do; usually a
transformation is applied to an entire container to change the look of
the entire container:
<Canvas>
<Canvas.RenderTransform>
<RotateTransform Angle="30"
CenterX="150"
CenterY="150" />
</Canvas.RenderTransform>
<Ellipse Width="300"
Height="300"
Stroke="Black"
Fill="Yellow"
StrokeThickness="2" />
<Ellipse Fill="Black"
Width="50"
Height="50"
Canvas.Left="50"
Canvas.Top="75" />
<Ellipse Fill="Black"
Width="50"
Height="50"
Canvas.Left="200"
Canvas.Top="75" />
<Path Stroke="Black"
StrokeThickness="5"
Data="M 50,200 S 150,275 250,200" />
</Canvas>
In this case the entire smiley face design is rotated (as seen in Figure 2).
The different types of Transformations are shown in Table 1.
Table 1. Tranformation Types
Type | Description | Example |
---|
RotateTransform | Performs a two-dimensional rotation on an object or object tree. | <RotateTransform Angle=“30” /> |
SkewTransform | Performs a two-dimensional skew on an object or object tree. | <SkewTransform AngleX=“30” AngleY=“75” />
|
ScaleTransform | Scales an object or object tree. | <ScaleTransform ScaleX=“1.5” ScaleY=“.75” />
|
TranslateTransform | Moves an object or object tree in two-dimensions. | <TranslateTransform X=“1.5” Y=“.75” />
|
CompositeTransform | Performs a mix of rotation, skewing, scaling and translation in a preferred order. | <CompositeTransform Rotation=“30” ScaleX=“1.5” TranslateX=“150” />
|
The four basic types of transforms can be used singularly or if you need to mix transforms (e.g. scale and rotate) you can use CompositeTransform to apply multiple transforms together.
Animations
While the idea of
animations in applications may make you think of creating the next
billion-dollar grossing animated feature, that’s not what animations
are for at all. Animations are simply a way to change properties of
XAML elements over time. For example, a simple animation to change the
width of a rectangle would look like this:
<DoubleAnimation Storyboard.TargetName="theRectangle"
Storyboard.TargetProperty="Width"
From="50"
To="250"
Duration="00:00:05" />
Animation elements tell a specific property how to change over time. This example shows changing the width of an element named “theRectangle” from a width of 50 to 250 over five seconds. The attached properties (Storyboard.TargetName and Storyboard.TargetProperty) hint at the fact that animations are not executed on their own but are housed in a container called a Storyboard. For example:
<Grid.Resources>
<Storyboard x:Name="theStory">
<DoubleAnimation Storyboard.TargetName="theRectangle"
Storyboard.TargetProperty="Width"
From="50"
To="250"
Duration="00:00:05" />
</Storyboard>
</Grid.Resources>
The Storyboard is embedded in a Resources section (usually at the main container or UserControl level) and named so that it can be executed and controlled via code. The unit of work for animations is the Storyboard.
Storyboards can contain one or more animations but all animations are
executed concurrently (not consecutively). Therefore if we expand this
Storyboard to include two animations:
<Grid.Resources>
<Storyboard x:Name="theStory">
<DoubleAnimation Storyboard.TargetName="theRectangle"
Storyboard.TargetProperty="Width"
From="50"
To="250"
Duration="00:00:05" />
<DoubleAnimation Storyboard.TargetName="theEllipse"
Storyboard.TargetProperty="Opacity"
From="1"
To="0"
Duration="00:00:03" />
</Storyboard>
</Grid.Resources>
When this storyboard
is executed, both animations will execute at the same time (again
concurrently) even though the animations themselves are against
entirely different properties on different objects.
The animations you’ve seen so far have been of type DoubleAnimation.
These animations are used because the animation is changing a number (a
double value). There are also animations to change colors (ColorAnimation) and vectors (PointAnimation).
All three of these animation types change values over a consistent
timeframe (and are called timeline animations). There are also
animations called key frame animations. These animations also change
properties over time but the calculation is based on a value at a
specific time in the animation. For example:
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="theRectangle"
Storyboard.TargetProperty="Height">
<LinearDoubleKeyFrame KeyTime="00:00:00" Value="50" />
<LinearDoubleKeyFrame KeyTime="00:00:01" Value="150" />
<LinearDoubleKeyFrame KeyTime="00:00:03" Value="200" />
</DoubleAnimationUsingKeyFrames>
There are key frame animations for each of the timeline animations (e.g. double, point and color) but are named with the “UsingKeyFrames” postfix as shown above. The Storyboard attached properties are still used to signify the target of the animation, but instead of a simple To and From to specify the values of the animation, one or more key frames are used. For example, the LinearDoubleKeyFrame element specifies what time the value should be a specific numeric property.
In this case the height
should start at 50 at the start of the animation; move quickly over the
first second to 150 and finally slow down and move to 200 over the last
two seconds. The interpolation of the values between the key frames
depends on the type of key frame. In this example the interpolation is
linear. You can also use spline and discrete to achieve curved
interpolation and stepped interpolation respectively.
With these tools in hand, you
should be able to create the subtle interactive effects that give the
user the impression that they are interacting with real-world objects.